package com.algorithms.hash;

import com.algorithms.linkedlists.Link;
import com.algorithms.linkedlists.SortedLinkedList;

@SuppressWarnings("unchecked")
public class ChainHashTable<T extends Comparable<T>> {
	private SortedLinkedList<Integer>[] hashList;
	private int size;
	
	public ChainHashTable(int size){
		this.size = size;
		this.hashList = new SortedLinkedList[this.size];
		for (int i = 0; i < this.size; i++){
			this.hashList[i] = new SortedLinkedList<Integer>();
		}
	}
	
	/**
	 * insert an item to hash
	 * 
	 * @param key
	 * @param data
	 */
	public void insert(int key){
		int hashVal = hashFunc(key);
		hashList[hashVal].insert(key);
	}
	
	/**
	 * find item by key in hash
	 * 
	 * @param key
	 * @return
	 */
	public Integer find(int key){
		int hashVal = hashFunc(key);
		Link<Integer> foundItem = hashList[hashVal].find(key);
		if (foundItem != null){
			return foundItem.getContent();
		}
		return null;
	}
	
	public boolean delete(int key){
		int hashVal = hashFunc(key);
		Link<Integer> deletedItem = hashList[hashVal].delete(key);
		return deletedItem != null;
	}
	
	public void printHash(){
		System.out.println("table: ");
		for (int i = 0; i < this.size; i++){
			this.hashList[i].printElements();
			if (!this.hashList[i].isEmpty()){
				System.out.println();
			}
		}
		System.out.println();
	}
	
	/**
	 * map a key from real data to an index on hash list
	 * 
	 * @param key
	 * @return new potential index
	 */
	private int hashFunc(int key){
		return key % this.size;
	}
	
}
